<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>COSMIC功能点拆分工具</title>
    <style>
        :root {
            --primary-color: #4a6bdf;
            --secondary-color: #f5f7fa;
            --success-color: #4caf50;
            --warning-color: #ff9800;
            --error-color: #f44336;
            --border-color: #e0e0e0;
            --text-color: #333;
            --white: #ffffff;
            --guide-primary: #6c5ce7;
            --guide-secondary: #a29bfe;
            --header-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        }
        
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background-color: #f9fafc;
            color: var(--text-color);
            padding: 20px;
            line-height: 1.6;
        }
        
        .cosmic-container {
            max-width: 1200px;
            margin: 0 auto;
        }
        
        .page-header {
            text-align: center;
            margin-bottom: 30px;
            padding: 20px 0;
            background: var(--header-gradient);
            color: white;
            border-radius: 8px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
        }
        
        .page-header h1 {
            font-size: 2rem;
            font-weight: 600;
            margin-bottom: 5px;
        }
        
        .page-header p {
            opacity: 0.9;
            font-size: 1rem;
        }
        
        .panel {
            background-color: var(--white);
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            padding: 25px;
            margin-bottom: 25px;
        }
        
        .panel-title {
            font-weight: 600;
            margin-bottom: 20px;
            color: var(--primary-color);
            display: flex;
            align-items: center;
            gap: 10px;
            font-size: 1.2rem;
        }
        
        .panel-title i {
            font-size: 1.3rem;
        }
        
        .input-row {
            display: flex;
            gap: 20px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }
        
        .input-group {
            flex: 1;
            min-width: 200px;
        }
        
        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 500;
            color: #555;
        }
        
        input[type="text"], textarea, select {
            width: 100%;
            padding: 12px;
            border: 1px solid var(--border-color);
            border-radius: 6px;
            font-size: 1rem;
            transition: all 0.3s;
        }
        
        textarea {
            min-height: 120px;
            resize: vertical;
        }
        
        input[type="text"]:focus, textarea:focus, select:focus {
            outline: none;
            border-color: var(--primary-color);
            box-shadow: 0 0 0 3px rgba(74, 107, 223, 0.2);
        }
        
        .btn-container {
            display: flex;
            justify-content: center;
            gap: 15px;
            margin-top: 25px;
            flex-wrap: wrap;
        }
        
        .btn {
            padding: 12px 25px;
            border: none;
            border-radius: 6px;
            color: white;
            cursor: pointer;
            font-size: 1rem;
            transition: all 0.3s;
            display: inline-flex;
            align-items: center;
            gap: 10px;
            font-weight: 500;
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
        }
        
        .btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(0,0,0,0.15);
        }
        
        .btn-primary {
            background: var(--header-gradient);
        }
        
        .btn-primary:hover {
            opacity: 0.9;
        }
        
        .btn-success {
            background-color: var(--success-color);
        }
        
        .btn-success:hover {
            background-color: #3d8b40;
        }
        
        .cosmic-table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
        }
        
        .cosmic-table th, .cosmic-table td {
            border: 1px solid var(--border-color);
            padding: 14px 16px;
            text-align: center;
        }
        
        .cosmic-table th {
            background-color: var(--primary-color);
            color: white;
            font-weight: 600;
            position: sticky;
            top: 0;
        }
        
        .cosmic-table tr:nth-child(even) {
            background-color: var(--secondary-color);
        }
        
        .cosmic-table td {
            vertical-align: top;
        }
        
        .data-movement-cell {
            text-align: center;
            font-weight: 600;
            width: 80px;
        }
        
        .data-movement-header {
            text-align: center;
        }
        
        .data-movement-E {
            color: #1565c0;
            background-color: rgba(21, 101, 192, 0.1);
        }
        
        .data-movement-R {
            color: #ff8f00;
            background-color: rgba(255, 143, 0, 0.1);
        }
        
        .data-movement-W {
            color: #c62828;
            background-color: rgba(198, 40, 40, 0.1);
        }
        
        .data-movement-X {
            color: #6a1b9a;
            background-color: rgba(106, 27, 154, 0.1);
        }
        
        .result-stats {
            display: flex;
            gap: 20px;
            margin-bottom: 30px;
            flex-wrap: wrap;
            justify-content: center;
        }
        
        .stat-item {
            flex: 1;
            min-width: 160px;
            background-color: var(--white);
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
            text-align: center;
            transition: transform 0.3s;
        }
        
        .stat-item:hover {
            transform: translateY(-5px);
        }
        
        .stat-value {
            font-size: 2rem;
            font-weight: 600;
            margin: 10px 0;
            color: var(--primary-color);
        }
        
        .stat-label {
            font-size: 0.95rem;
            color: #666;
        }
        
        .error-message {
            color: var(--error-color);
            margin-top: 8px;
            font-size: 0.9rem;
            display: none;
        }
        
        .has-error {
            border-color: var(--error-color) !important;
        }
        
        /* Guide Table Styles */
        .guide-table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
        }
        
        .guide-table th {
            background-color: var(--guide-primary);
            color: white;
            padding: 14px;
            text-align: left;
            font-weight: 500;
        }
        
        .guide-table td {
            padding: 14px;
            border: 1px solid #eee;
            vertical-align: top;
        }
        
        .guide-table tr:nth-child(even) {
            background-color: #f9f9f9;
        }
        
        .guide-table tr:hover {
            background-color: #f1f1f1;
        }
        
        .guide-table .icon-cell {
            text-align: center;
            width: 50px;
            color: var(--guide-primary);
            font-size: 1.2rem;
        }
        
        .guide-table .title-cell {
            font-weight: 600;
            color: var(--guide-primary);
        }
        
        .guide-table .example-box {
            background-color: #f5f7ff;
            padding: 10px 15px;
            border-radius: 6px;
            margin-top: 10px;
            font-style: italic;
            border-left: 3px solid var(--guide-secondary);
        }
        
        .guide-table ul {
            margin-left: 20px;
            padding-left: 0;
        }
        
        .guide-table li {
            margin-bottom: 8px;
            position: relative;
            list-style-type: none;
            padding-left: 20px;
        }
        
        .guide-table li:before {
            content: "•";
            color: var(--guide-primary);
            position: absolute;
            left: 0;
            font-weight: bold;
        }
        
        @media (max-width: 768px) {
            .cosmic-table, .guide-table {
                display: block;
                overflow-x: auto;
            }
            
            .btn {
                width: 100%;
                justify-content: center;
            }
            
            .btn-container {
                flex-direction: column;
            }
            
            .result-stats {
                flex-direction: column;
                align-items: center;
            }
            
            .stat-item {
                min-width: 80%;
            }
            
            .input-row {
                flex-direction: column;
                gap: 15px;
            }
            
            .input-group {
                min-width: 100%;
            }
            
            .page-header {
                padding: 15px 10px;
            }
            
            .page-header h1 {
                font-size: 1.5rem;
            }
        }
    </style>
    <link rel="stylesheet" href="../css/all.min.css">
</head>
<body>
    <div class="cosmic-container">
        <header class="page-header">
            <h1>COSMIC功能点拆分工具</h1>
            <p>基于COSMIC方法的标准功能点分析与计算工具</p>
        </header>
        
        <div class="panel">
            <div class="panel-title"><i class="fas fa-edit"></i> 功能点基本信息</div>
            <div class="input-row">
                <div class="input-group">
                    <label for="module-name">模块名称</label>
                    <input type="text" id="module-name" placeholder="输入模块名称，如：用户管理">
                </div>
                <div class="input-group">
                    <label for="trigger-event">触发事件</label>
                    <input type="text" id="trigger-event" placeholder="描述触发事件，如：点击添加按钮">
                    <div class="error-message" id="trigger-error">触发事件不能为空</div>
                </div>
                <div class="input-group">
                    <label for="process-scope">功能范围</label>
                    <select id="process-scope">
                        <option value="custom">自定义功能</option>
                        <option value="add">添加功能</option>
                        <option value="edit">修改功能</option>
                        <option value="delete">删除功能</option>
                        <option value="export">导出功能</option>
                        <option value="import">导入功能</option>
                        <option value="search">查询功能</option>
                        <option value="list">列表功能</option>
                        <option value="paging">分页功能</option>
                        <option value="detail">查看详情</option>
                        <option value="preview">预览功能</option>
                    </select>
                </div>
            </div>
            <div class="input-group">
                <label for="related-fields">涉及字段</label>
                <input type="text" id="related-fields" placeholder="输入涉及的字段，用逗号分隔，如：用户名,密码,邮箱">
            </div>
            <div class="btn-container">
                <button id="generate-btn" class="btn btn-primary"><i class="fas fa-magic"></i> 生成功能过程</button>
                <button id="new-trigger-btn" class="btn btn-success"><i class="fas fa-redo"></i> 刷新</button>
            </div>
        </div>
        
        <div class="panel" id="result-panel" style="display: none;">
            <div class="panel-title"><i class="fas fa-chart-bar"></i> 功能点分析结果</div>
            
            <div class="result-stats">
                <div class="stat-item">
                    <div class="stat-label">总功能点</div>
                    <div class="stat-value" id="total-cfp">0</div>
                    <div>CFP</div>
                </div>
                <div class="stat-item">
                    <div class="stat-label">输入 (E)</div>
                    <div class="stat-value" id="entry-count">0</div>
                    <div>数据移动类型</div>
                </div>
                <div class="stat-item">
                    <div class="stat-label">读 (R)</div>
                    <div class="stat-value" id="read-count">0</div>
                    <div>数据移动类型</div>
                </div>
                <div class="stat-item">
                    <div class="stat-label">写 (W)</div>
                    <div class="stat-value" id="write-count">0</div>
                    <div>数据移动类型</div>
                </div>
                <div class="stat-item">
                    <div class="stat-label">输出 (X)</div>
                    <div class="stat-value" id="exit-count">0</div>
                    <div>数据移动类型</div>
                </div>
            </div>
            
            <table class="cosmic-table">
                <thead>
                    <tr>
                        <th width="20%">触发事件</th>
                        <th width="15%">功能过程</th>
                        <th width="20%">子过程描述</th>
                        <th width="15%" class="data-movement-header">数据移动类型</th>
                        <th width="15%">数据组</th>
                        <th width="15%">数据属性</th>
                    </tr>
                </thead>
                <tbody id="cosmic-result">
                    <!-- 结果将在这里动态生成 -->
                </tbody>
            </table>
        </div>
        
        <div class="panel" id="guide-panel">
            <div class="panel-title"><i class="fas fa-info-circle"></i> COSMIC 标准指南</div>
            
            <table class="guide-table">
                <tr>
                    <td class="icon-cell"><i class="fas fa-bolt"></i></td>
                    <td class="title-cell">触发事件</td>
                    <td>
                        <p>描述是因为什么触发的事件</p>
                        <div class="example-box">
                            例1：推送告警信息<br>
                            例2：用户提交订单<br>
                            例3：系统定时任务执行
                        </div>
                    </td>
                </tr>
                <tr>
                    <td class="icon-cell"><i class="fas fa-project-diagram"></i></td>
                    <td class="title-cell">功能过程</td>
                    <td>
                        <p>和功能架构图或流程图对应，是用户可感知的最小单元</p>
                        <div class="example-box">
                            例1：接收用户输入<br>
                            例2：验证数据有效性<br>
                            例3：保存到数据库
                        </div>
                    </td>
                </tr>
                <tr>
                    <td class="icon-cell"><i class="fas fa-project-diagram"></i></td>
                    <td class="title-cell">子过程</td>
                    <td>
                        <p>实现功能过程的数据移动，主谓宾描述，主语必须与功能用户中的"发送者"或"接收者"一致</p>
                        <div class="example-box">
                            例1：获取用户输入的表单数据<br>
                            例2：检查数据完整性和有效性<br>
                            例3：将新记录存入数据库
                        </div>
                    </td>
                </tr>
                <tr>
                    <td class="icon-cell"><i class="fas fa-exchange-alt"></i></td>
                    <td class="title-cell">数据移动类型</td>
                    <td>
                        <p>描述数据移动的方向和类型，只能填写 E、X、R、W</p>
                        <div class="example-box">
                            <span class="data-movement-E">E</span>: 输入 (Entry) - 数据从功能用户到功能处理<br>
                            <span class="data-movement-R">R</span>: 读 (Read) - 数据从持久存储到功能处理<br>
                            <span class="data-movement-W">W</span>: 写 (Write) - 数据从功能处理到持久存储<br>
                            <span class="data-movement-X">X</span>: 输出 (Exit) - 数据从功能处理到功能用户
                        </div>
                    </td>
                </tr>
                <tr>
                    <td class="icon-cell"><i class="fas fa-database"></i></td>
                    <td class="title-cell">数据组</td>
                    <td>
                        <p>一个移动类型对应一个数据组，命名规范：模块名称+数据</p>
                        <div class="example-box">
                            例1：用户数据<br>
                            例2：订单数据<br>
                            例3：产品信息
                        </div>
                    </td>
                </tr>
                <tr>
                    <td class="icon-cell"><i class="fas fa-database"></i></td>
                    <td class="title-cell">数据属性</td>
                    <td>
                        <p>数据组中包含的具体字段或属性</p>
                        <div class="example-box">
                            例1：用户名,密码,邮箱<br>
                            例2：订单号,商品ID,数量<br>
                            例3：产品名称,价格,库存
                        </div>
                    </td>
                </tr>
            </table>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const moduleNameInput = document.getElementById('module-name');
            const triggerInput = document.getElementById('trigger-event');
            const relatedFieldsInput = document.getElementById('related-fields');
            const processScopeSelect = document.getElementById('process-scope');
            const generateBtn = document.getElementById('generate-btn');
            const newTriggerBtn = document.getElementById('new-trigger-btn');
            const resultPanel = document.getElementById('result-panel');
            const cosmicResult = document.getElementById('cosmic-result');
            const totalCfp = document.getElementById('total-cfp');
            const entryCount = document.getElementById('entry-count');
            const readCount = document.getElementById('read-count');
            const writeCount = document.getElementById('write-count');
            const exitCount = document.getElementById('exit-count');
            const triggerError = document.getElementById('trigger-error');
            const guidePanel = document.getElementById('guide-panel');
            
            // 知识库 - 根据不同功能范围预定义的功能点模板
            const knowledgeBase = {
                'add': [
                    { process: "接收输入数据", subProcess: "获取用户输入的表单数据", movement: "E", group: "表单数据", attr: "所有输入字段" },
                    { process: "验证输入", subProcess: "检查数据完整性和有效性", movement: "R", group: "验证规则", attr: "必填字段,格式规则" },
                    { process: "生成唯一标识", subProcess: "为新记录创建唯一ID", movement: "R", group: "ID生成规则", attr: "ID格式,序列号" },
                    { process: "保存数据", subProcess: "将新记录存入数据库", movement: "W", group: "业务数据", attr: "所有字段值" },
                    { process: "返回结果", subProcess: "向用户显示操作结果", movement: "X", group: "操作结果", attr: "状态,新记录ID" }
                ],
                'edit': [
                    { process: "接收编辑请求", subProcess: "获取用户要编辑的记录ID", movement: "E", group: "请求参数", attr: "记录ID" },
                    { process: "查询原数据", subProcess: "从数据库获取原始记录", movement: "R", group: "业务数据", attr: "所有字段值" },
                    { process: "接收修改数据", subProcess: "获取用户修改的字段值", movement: "E", group: "修改数据", attr: "变更字段" },
                    { process: "验证修改", subProcess: "检查修改是否符合规则", movement: "R", group: "业务规则", attr: "验证规则" },
                    { process: "更新数据", subProcess: "将修改保存到数据库", movement: "W", group: "业务数据", attr: "变更字段" },
                    { process: "返回结果", subProcess: "向用户显示更新结果", movement: "X", group: "操作结果", attr: "状态,更新时间" }
                ],
                'delete': [
                    { process: "接收删除请求", subProcess: "获取用户要删除的记录ID", movement: "E", group: "请求参数", attr: "记录ID" },
                    { process: "验证删除权限", subProcess: "检查用户是否有删除权限", movement: "R", group: "权限规则", attr: "用户角色,权限" },
                    { process: "检查关联数据", subProcess: "验证记录是否有关联数据", movement: "R", group: "关联数据", attr: "外键关系" },
                    { process: "执行删除", subProcess: "从数据库删除记录", movement: "W", group: "业务数据", attr: "记录ID" },
                    { process: "记录操作", subProcess: "保存删除操作日志", movement: "W", group: "操作日志", attr: "操作者,时间" },
                    { process: "返回结果", subProcess: "向用户显示删除结果", movement: "X", group: "操作结果", attr: "状态,删除记录ID" }
                ],
                'export': [
                    { process: "接收导出请求", subProcess: "获取用户导出参数", movement: "E", group: "导出参数", attr: "格式,范围" },
                    { process: "查询数据", subProcess: "从数据库获取导出数据", movement: "R", group: "业务数据", attr: "所有相关字段" },
                    { process: "生成导出文件", subProcess: "按指定格式生成文件", movement: "R", group: "模板规则", attr: "文件格式,模板" },
                    { process: "记录导出", subProcess: "保存导出操作日志", movement: "W", group: "操作日志", attr: "操作者,时间" },
                    { process: "返回文件", subProcess: "向用户提供导出文件", movement: "X", group: "导出文件", attr: "文件名,下载链接" }
                ],
                'import': [
                    { process: "接收导入文件", subProcess: "获取用户选择的文件", movement: "E", group: "导入文件", attr: "文件名,格式" },
                    { process: "解析文件", subProcess: "读取并解析文件内容", movement: "R", group: "解析规则", attr: "格式规范" },
                    { process: "验证数据", subProcess: "检查导入数据有效性", movement: "R", group: "业务规则", attr: "验证规则" },
                    { process: "处理导入", subProcess: "将数据保存到数据库", movement: "W", group: "业务数据", attr: "所有字段" },
                    { process: "记录导入", subProcess: "保存导入操作日志", movement: "W", group: "操作日志", attr: "操作者,时间" },
                    { process: "返回结果", subProcess: "向用户显示导入结果", movement: "X", group: "导入结果", attr: "状态,记录数" }
                ],
                'search': [
                    { process: "接收搜索条件", subProcess: "获取用户输入的搜索参数", movement: "E", group: "搜索条件", attr: "关键词,筛选条件" },
                    { process: "构建查询", subProcess: "根据条件构建查询语句", movement: "R", group: "查询规则", attr: "查询逻辑" },
                    { process: "执行查询", subProcess: "从数据库获取匹配结果", movement: "R", group: "业务数据", attr: "所有相关字段" },
                    { process: "处理结果", subProcess: "对查询结果进行排序过滤", movement: "R", group: "排序规则", attr: "排序字段,方式" },
                    { process: "返回结果", subProcess: "向用户显示搜索结果", movement: "X", group: "搜索结果", attr: "记录列表,总数" }
                ],
                'list': [
                    { process: "接收列表请求", subProcess: "获取用户列表查看请求", movement: "E", group: "请求参数", attr: "无" },
                    { process: "查询数据", subProcess: "从数据库获取列表数据", movement: "R", group: "业务数据", attr: "所有列表字段" },
                    { process: "处理数据", subProcess: "对数据进行格式化处理", movement: "R", group: "格式化规则", attr: "显示格式" },
                    { process: "返回列表", subProcess: "向用户显示数据列表", movement: "X", group: "列表数据", attr: "记录集合" }
                ],
                'paging': [
                    { process: "接收分页请求", subProcess: "获取用户分页参数", movement: "E", group: "分页参数", attr: "页码,每页条数" },
                    { process: "查询总数", subProcess: "获取符合条件的总记录数", movement: "R", group: "业务数据", attr: "COUNT值" },
                    { process: "查询数据", subProcess: "获取当前页数据", movement: "R", group: "业务数据", attr: "所有列表字段" },
                    { process: "计算分页", subProcess: "计算分页相关信息", movement: "R", group: "分页规则", attr: "总页数,当前页" },
                    { process: "返回结果", subProcess: "向用户显示分页数据", movement: "X", group: "分页结果", attr: "当前页数据,分页信息" }
                ],
                'detail': [
                    { process: "接收详情请求", subProcess: "获取用户要查看的记录ID", movement: "E", group: "请求参数", attr: "记录ID" },
                    { process: "查询数据", subProcess: "从数据库获取详细数据", movement: "R", group: "业务数据", attr: "所有字段值" },
                    { process: "查询关联数据", subProcess: "获取相关关联数据", movement: "R", group: "关联数据", attr: "关联字段" },
                    { process: "组装详情", subProcess: "组织详情页面所需数据", movement: "R", group: "展示规则", attr: "展示模板" },
                    { process: "返回详情", subProcess: "向用户显示详情信息", movement: "X", group: "详情数据", attr: "所有字段,关联数据" }
                ],
                'preview': [
                    { process: "接收预览请求", subProcess: "获取用户预览参数", movement: "E", group: "预览参数", attr: "内容ID,格式" },
                    { process: "查询内容", subProcess: "从数据库获取预览内容", movement: "R", group: "内容数据", attr: "原始内容" },
                    { process: "处理内容", subProcess: "按预览格式处理内容", movement: "R", group: "处理规则", attr: "格式规范" },
                    { process: "生成预览", subProcess: "生成最终预览效果", movement: "R", group: "模板规则", attr: "预览模板" },
                    { process: "返回预览", subProcess: "向用户显示预览结果", movement: "X", group: "预览内容", attr: "格式化内容" }
                ],
                'custom': [
                    { process: "接收输入", subProcess: "获取用户输入数据", movement: "E", group: "输入数据", attr: "相关输入字段" },
                    { process: "验证输入", subProcess: "检查数据有效性", movement: "R", group: "验证规则", attr: "验证条件" },
                    { process: "处理业务", subProcess: "执行业务逻辑处理", movement: "R", group: "业务规则", attr: "处理逻辑" },
                    { process: "保存结果", subProcess: "将处理结果持久化", movement: "W", group: "业务数据", attr: "结果字段" },
                    { process: "返回输出", subProcess: "向用户返回处理结果", movement: "X", group: "输出数据", attr: "状态,结果" }
                ]
            };
            
            // 智能生成功能点
            generateBtn.addEventListener('click', function() {
                const trigger = triggerInput.value.trim();
                const moduleName = moduleNameInput.value.trim();
                const relatedFields = relatedFieldsInput.value.trim();
                const scope = processScopeSelect.value;
                
                // 验证触发事件
                if (!validateTrigger(trigger)) {
                    return;
                }
                
                // 根据范围获取模板
                let template = knowledgeBase[scope] || knowledgeBase['custom'];
                
                // 处理模块名称和涉及字段
                const fullTrigger = moduleName ? `${moduleName} - ${trigger}` : trigger;
                
                // 更新数据组名称和涉及字段
                template = template.map(item => {
                    // 更新数据组名称
                    let newGroup = item.group;
                    if (moduleName && (item.group.includes("数据") || item.group === "表单数据")) {
                        newGroup = `${moduleName}数据`;
                    }
                    
                    // 更新数据属性
                    let newAttr = item.attr;
                    if (relatedFields && (item.attr.includes("字段") || item.group.includes("数据"))) {
                        newAttr = relatedFields.split(',').map(f => f.trim()).join(',');
                    }
                    
                    return {
                        ...item,
                        group: newGroup,
                        attr: newAttr
                    };
                });
                
                // 生成结果
                generateResult(fullTrigger, template);
                
                // 显示结果面板，隐藏指南
                resultPanel.style.display = 'block';
                guidePanel.style.display = 'none';
            });
            
            // 验证触发事件
            function validateTrigger(trigger) {
                if (!trigger) {
                    triggerInput.classList.add('has-error');
                    triggerError.textContent = '触发事件不能为空';
                    triggerError.style.display = 'block';
                    return false;
                }
                
                triggerInput.classList.remove('has-error');
                triggerError.style.display = 'none';
                return true;
            }
            
            // 生成结果表格
            function generateResult(trigger, template) {
                cosmicResult.innerHTML = '';
                
                let eCount = 0, rCount = 0, wCount = 0, xCount = 0;
                
                template.forEach((item, index) => {
                    const row = document.createElement('tr');
                    
                    // 第一列只在第一行显示触发事件
                    const triggerCell = document.createElement('td');
                    if (index === 0) {
                        triggerCell.textContent = trigger;
                        triggerCell.rowSpan = template.length;
                    } else {
                        triggerCell.style.display = 'none';
                    }
                    
                    row.innerHTML = `
                        <td>${item.process}</td>
                        <td>${item.subProcess}</td>
                        <td class="data-movement-cell data-movement-${item.movement}">${item.movement}</td>
                        <td>${item.group}</td>
                        <td>${item.attr}</td>
                    `;
                    
                    row.prepend(triggerCell);
                    cosmicResult.appendChild(row);
                    
                    // 统计数据移动
                    switch(item.movement) {
                        case 'E': eCount++; break;
                        case 'R': rCount++; break;
                        case 'W': wCount++; break;
                        case 'X': xCount++; break;
                    }
                });
                
                // 更新统计
                const total = eCount + rCount + wCount + xCount;
                totalCfp.textContent = total;
                entryCount.textContent = eCount;
                readCount.textContent = rCount;
                writeCount.textContent = wCount;
                exitCount.textContent = xCount;
            }
            
            // 新建触发事件
            newTriggerBtn.addEventListener('click', function() {
                triggerInput.value = '';
                relatedFieldsInput.value = '';
                resultPanel.style.display = 'none';
                guidePanel.style.display = 'block';
                triggerInput.focus();
            });
        });
    </script>
</body>
</html>